using UnityEngine;
using UnityEditor;

namespace LCH
{
    /// <summary>
    /// 网格绘制器 - 绘制逻辑功能模块
    /// </summary>
    public partial class LchMeshPainter
    {
        /// <summary>
        /// 平滑FlowMap纹理
        /// </summary>
        private void SmoonthFlowMap()
        {
            RenderTexture rt = new RenderTexture(editorFlowMapRT.width/2, editorFlowMapRT.height/2, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);

            Graphics.Blit(editorFlowMapRT, rt);
            Graphics.Blit(rt, editorFlowMapRT);
            GameObject.DestroyImmediate(rt,true);

        }
        
        /// <summary>
        /// 绘制顶点颜色
        /// </summary>
        void OnPlaintVertex()
        {
            if (!isDragging)
                return;
            if (!isMouseOnMesh)
                return;
            if (!sceneCamera)
                return;
            if (selectObjectMesh == null)
                return;
            if (null == brush)
                return;

            Vector3 [] vertices = selectObjectMesh.vertices;
            Vector3[] normals = selectObjectMesh.normals;
            Color[] colors = selectObjectMesh.colors;
            if (colors.Length == 0)
            {
                colors = new Color[vertices.Length];
                for (int i = 0; i < colors.Length; i++)
                {
                    colors[i] = Color.white;
                }
            }
            var localToWorld = selectObject.transform.localToWorldMatrix;
            var viewForward = sceneCamera.transform.forward;

            var worldToBrush = brush.transform.worldToLocalMatrix;

            
            if (vertexBrushType ==0)
            {
                switch (editingChannel)
                {
                    case 1:
                        vertexBrushColor = new Color(0f, 1f, 0f, 0f);
                        break;
                    case 2:
                        vertexBrushColor = new Color(0f, 0f, 1f, 0f);
                        break;
                    case 3:
                        vertexBrushColor = new Color(0f, 0f, 0f, 1f);
                        break;
                    default:
                        vertexBrushColor = new Color(1f, 0f, 0f, 0f);
                        break;
                }
            }
            
            for (int i = 0; i < vertices.Length; i++)
            {
                var worldForward = localToWorld.MultiplyVector(normals[i]);
                if (Vector3.Dot(worldForward, viewForward) <= 0)
                {
                    var worldPos = localToWorld.MultiplyPoint(vertices[i]);
                    var localPos = worldToBrush.MultiplyPoint(worldPos);
                   
                    if (Mathf.Abs(localPos.x) <= 1f && Mathf.Abs(localPos.y) < 1f)
                    {
                        
                        float r = Mathf.Sqrt(localPos.x * localPos.x + localPos.y * localPos.y);
                        r = Mathf.Clamp01(1f- r);
                        if (r > 0)
                        {
                            colors[i] = Color.Lerp(colors[i], vertexBrushColor, r* brushStrength);
                            isVertexDirty = true;
                        }
                    }
                }
            }
            selectObjectMesh.colors = colors;
        }

        /// <summary>
        /// 绘制FlowMap纹理
        /// </summary>
        public void OnPlaintFlowMap()
        {
            if (!isDragging)
                return;
            if (!isMouseOnMesh)
                return;
            isTextureFlowMaplDirty = true;
            isFlowMapDirty = true;
            Texture  source = null;

            if (null != editorFlowMapRT)
            {
                source = editorFlowMapRT ;
                editorFlowMapRT = new RenderTexture(source .width, source .height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);

            }
            else if (null == flowMapTex)
            {
                source = Texture2D.redTexture;
                editorFlowMapRT = new RenderTexture(512, 512, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);

            }
            else
            {
                source = flowMapTex;
                editorFlowMapRT = new RenderTexture(flowMapTex.width, flowMapTex.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);

            }
            editorFlowMapRT.filterMode = FilterMode.Point;
            if (null == brushing_flowmap)
                brushing_flowmap = new Material(Shader.Find("Hidden/BushingFlowMap"));

     
            brushing_flowmap.SetTexture("_BrushTex", brushTexture);
            brushing_flowmap.SetTexture("_MainTex", source);
            brushing_flowmap.SetFloat("_BrushStrong", brushStrength);
            brushing_flowmap.SetFloat("_BrushMaxStrong", brushMaxStrength);

            Graphics.Blit(source, editorFlowMapRT, brushing_flowmap);

            selectObjectMaterial.SetTexture(setting.flowMapTextureName, editorFlowMapRT);
            if (source != null && source is RenderTexture)
            {
                GameObject.DestroyImmediate(source, true);
            }
        }
        
        /// <summary>
        /// 绘制控制图纹理
        /// 对所有控制图进行绘制，shader会根据通道索引自动处理混合
        /// </summary>
        private void OnPlaint()
        {
            if (!isDragging)
                return;
            if (!isMouseOnMesh)
                return;
            if (controlTextureCount == 0)
                return;

            if (null == brushing)
                brushing = new Material(Shader.Find("Hidden/Bushing"));

            isTextureChannelDirty = true;
            Texture[] source = new Texture[controlTextureCount];

            // 为所有控制图准备source和RenderTexture
            for (int i = 0; i < controlTextureCount; i++)
            {
                if (!ControlTextureOperations.IsValidControlTextureIndex(i, controlTextureCount, ctrlText, editorCtrl1RT))
                    continue;
                    
                if (null != editorCtrl1RT[i])
                {
                    source[i] = editorCtrl1RT[i];
                    editorCtrl1RT[i] = new RenderTexture(source[i].width, source[i].height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                    // 复制source内容到新RT
                    Graphics.Blit(source[i], editorCtrl1RT[i]);
                }
                else if (null == ctrlText[i])
                {
                    source[i] = (i == 0) ? Texture2D.redTexture : Texture2D.blackTexture;
                    editorCtrl1RT[i] = new RenderTexture(ControlTextureConstants.DEFAULT_CONTROL_TEXTURE_SIZE, ControlTextureConstants.DEFAULT_CONTROL_TEXTURE_SIZE, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                    // 复制source内容到新RT
                    Graphics.Blit(source[i], editorCtrl1RT[i]);
                }
                else
                {
                    source[i] = ctrlText[i];
                    editorCtrl1RT[i] = new RenderTexture(ctrlText[i].width, ctrlText[i].height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                    // 复制source内容到新RT
                    Graphics.Blit(source[i], editorCtrl1RT[i]);
                }
            }

            // 计算当前编辑的控制图索引和通道索引
            int ctrlIndex = editingChannel / ControlTextureConstants.CHANNELS_PER_CONTROL_TEXTURE;
            int channelIndex = editingChannel % ControlTextureConstants.CHANNELS_PER_CONTROL_TEXTURE;
            
            // 确保索引有效
            if (ctrlIndex >= controlTextureCount)
                ctrlIndex = controlTextureCount - 1;
            if (ctrlIndex < 0)
                ctrlIndex = 0;
            
            // 方案2：先计算变化比例到临时RT，然后根据这个RT修改所有控制图
            // 步骤1：创建临时RT用于存储变化比例
            RenderTexture ratioRT = null;
            if (source[ctrlIndex] != null)
            {
                int rtWidth = source[ctrlIndex].width;
                int rtHeight = source[ctrlIndex].height;
                ratioRT = new RenderTexture(rtWidth, rtHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                
                // 步骤2：使用Pass 1计算变化比例，从正在编辑的控制图读取旧值
                brushing.SetTexture("_OperaingTex", source[ctrlIndex]);
                brushing.SetFloat("_BrushIndexInOperaTex", channelIndex);
                brushing.SetTexture("_BrushTex", brushTexture);
                brushing.SetFloat("_BrushStrong", brushStrength);
                brushing.SetFloat("_BrushMaxStrong", brushMaxStrength);
                
                // 使用Pass 1（CalculateRatio）计算变化比例
                Graphics.Blit(source[ctrlIndex], ratioRT, brushing, 1);
            }
            
            // 步骤3：对所有控制图使用Pass 0，从变化比例RT读取sub值
            if (ratioRT != null)
            {
                for (int i = 0; i < controlTextureCount; i++)
                {
                    if (!ControlTextureOperations.IsValidControlTextureIndex(i, controlTextureCount, ctrlText, editorCtrl1RT))
                        continue;
                    
                    // 计算当前控制图的起始通道索引
                    int ctrlStartChannel = i * ControlTextureConstants.CHANNELS_PER_CONTROL_TEXTURE;
                    
                    // 计算当前控制图内部的通道索引（相对于当前控制图）
                    // 如果编辑的通道在当前控制图范围内，得到0-3；否则得到负数或大于3的值，shader不会匹配，所有通道变暗
                    int localChannelIndex = editingChannel - ctrlStartChannel;
                    
                    // 设置绘制参数
                    // 使用变化比例RT，确保所有控制图使用相同的变化比例
                    brushing.SetTexture("_RatioTex", ratioRT);
                    brushing.SetFloat("_BrushIndexInMainTex", localChannelIndex);
                    brushing.SetTexture("_MainTex", ctrlText[i] != null ? ctrlText[i] : (i == 0 ? Texture2D.redTexture : Texture2D.blackTexture));
                    
                    // 使用Pass 0绘制到对应的控制图（从变化比例RT读取sub值）
                    Graphics.Blit(source[i], editorCtrl1RT[i], brushing, 0);
                    
                    // 更新到material
                    if (i < detectedCtrlTextureNames.Count)
                    {
                        selectObjectMaterial.SetTexture(detectedCtrlTextureNames[i], editorCtrl1RT[i]);
                    }
                }
                
                // 清理临时RT
                GameObject.DestroyImmediate(ratioRT, true);
            }
            for (int i = 0; i < source.Length; i++)
            {
                if (source[i] != null && source[i] is RenderTexture)
                {
                    GameObject.DestroyImmediate(source[i], true);
                }
            }
        }
    }
}

